#pragma once
#include "Comm.hpp"
#include "Sock.hpp"
#include "Epoll.hpp"
#include "Log.hpp"
#include "Protocol.hpp"
#include "RingQueue.hpp"
#include "../myDecision/DecisionMaking.hpp"
class TcpServer;
class Connection;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
using func_t = std::function<void(Connection *)>;
using callback_t = std::function<void(Connection *, std::string &request)>;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 每个sock 必须具备自己独立的接受和发送缓冲区
// struct Point
// {
//     Point(int x = -1, int y = -1)
//         : _x(x), _y(y)
//     {
//     }
//     ~Point() {}
//     int _x;
//     int _y;
// };
class Connection
{
public:
    Connection(int sock = -1) : _sock(sock), _tsvr(nullptr)
    {
    }
    void SetCallBack(func_t recv_cb, func_t send_cb, func_t execpt_cb)
    {
        _recv_cb = recv_cb;
        _send_cb = send_cb;
        _except_cb = execpt_cb;
    }
    ~Connection()
    {
        if (_sock)
            close(_sock);
    }

public:
    int _sock; // 需要管理的套接字
    func_t _recv_cb;
    func_t _send_cb;
    func_t _except_cb;

    std::string _inbuffer;  // 接收缓冲区
    std::string _outbuffer; // 发送缓冲区

    // 设置对TcpServer 的回指指针
    TcpServer *_tsvr; // 第一次激活写入状态

    // 时间戳--处理长时间不活跃的连接
    uint64_t _last_time_stamp;
};
class TcpServer
{
    const static int gport = 8888; // 服务器端口号
    const static int gnum = 128;   // sock就绪缓冲区大小
public:
    TcpServer(int port = gport) : _port(port), _revs_num(gnum)
    {
        // 1.创建监听套接字
        _listensock = Sock::Socket();
        Sock::Bind(_listensock, _port);
        Sock::Listen(_listensock);

        // 2.创建多路转接对象
        _epfd.CreatePoll();

        // 3.将监听套接字listensock加入多路转接进行等待
        AddConnection(_listensock, std::bind(&TcpServer::Accepter, this, std::placeholders::_1), nullptr, nullptr);

        // 4.构建获取就绪事件的缓冲区
        _revs = new struct epoll_event[_revs_num];

        // 5.开辟环形队列空间
         _rqp = new RingQueue<int>;
         _rqc = new RingQueue<size_t>;
         _rqv = new RingQueue<size_t>;
         _rqt = new RingQueue<size_t>;

        // _rqp = nullptr;
        // _rqc = nullptr;
        // _rqv = nullptr;
        // _rqt = nullptr;
    }
    // 此函数 专门将sock 添加到TcpServer，进行等待，设定配置服务
    void AddConnection(int sock, func_t recv_cb, func_t send_cb, func_t except_cb)
    {
        // 将监听套接字设为非阻塞
        Sock::SetNonBlock(sock);

        // 1.构建Connection对象,封装sock
        Connection *con = new Connection(sock);
        con->SetCallBack(recv_cb, send_cb, except_cb);
        con->_tsvr = this;
        con->_last_time_stamp = time(nullptr); // 获取第一次设置的时间戳
        // 2.添加sock到epoll
        _epfd.AddSockToEpoll(sock, EPOLLIN | EPOLLET); // sock默认开启读取事件，写入事件在需要时打开
        // 3.构建sock与connection的映射关系进行管理
        _connections.insert(std::make_pair(sock, con));
    }
    // 此函数用来获取提供服务的套接字
    void Accepter(Connection *conn)
    {
        // logMessage(DEBUG,"accepter benn call");
        // 此时listensock 一定就绪,需要获得提供服务的sock
        while (true) // 使用while不断读取，ET模式
        {
            conn->_last_time_stamp = time(nullptr);
            std::string clientip;
            uint16_t clientport;
            int accept_errno = 0;
            // 此sock为正常IO sock
            int sock = Sock::Accept(conn->_sock, &clientip, &clientport, &accept_errno);
            if (sock < 0)
            {

                // 情况1
                if (accept_errno == EAGAIN || accept_errno == EWOULDBLOCK)
                {
                    // 底层没有文件描述符了
                    break;
                }
                // 情况2
                else if (accept_errno == EINTR)
                    continue;
                else // 情况3
                {
                    // sock获取失败
                    logMessage(WARNING, "accept error,%d:%s", accept_errno, strerror(accept_errno));
                    break;
                }
            }

            if (sock >= 0) // 将sock托管给TcpServer
            {
                AddConnection(sock, std::bind(&TcpServer::Recver, this, std::placeholders::_1),
                              std::bind(&TcpServer::Sender, this, std::placeholders::_1),
                              std::bind(&TcpServer::Excepter, this, std::placeholders::_1));
                logMessage(DEBUG, "accept client %s:%d success,add to epoll && TcpServer success,sock:%d", clientip.c_str(), clientport, sock);
            }
        }
    }
    // 此函数为接受传输数据函数
    void Recver(Connection *conn)
    {
        conn->_last_time_stamp = time(nullptr);
        static const int b_num = 1024;
        bool err = false;
        logMessage(DEBUG, "conn->recv");
        while (true)
        {
            char buffer[b_num];
            ssize_t n = recv(conn->_sock, buffer, sizeof(buffer) - 1, 0);
            if (n < 0)
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                    break; // 读取结束，缓冲区无内容
                else if (errno == EINTR)
                    continue;
                else
                {
                    logMessage(ERROR, "recv error,%d : %s", errno, strerror(errno));
                    conn->_except_cb(conn); // 将错误交给异常处理
                    err = true;
                    break;
                }
            }
            else if (n == 0) // 对端关闭
            {
                logMessage(DEBUG, "client  quit,me too");
                conn->_except_cb(conn);
                err = true;
                break;
            }
            else
            {
                // 读取成功
                buffer[n] = 0;
                // logMessage(NORMAL,"读取数据:%s",buffer);
                conn->_inbuffer += buffer; // 将数据拷贝到sock对应的输入缓冲区
            }
        }
        logMessage(DEBUG, "conn->_inbuffer[sock:%d]:%s", conn->_sock, conn->_inbuffer.c_str());
        // logMessage(DEBUG,"err:%s",err==true?"true":"false");
        if (!err) // 进入此证明是正常读取内容
        {
            // 将内容进行处理
            std::vector<std::string> message;
            DeCode(conn->_inbuffer, &message);
            // 此时一定是一个完整的报文
            for (auto &msg : message)
            {
                // logMessage(NORMAL,"报文:%s",msg.c_str());
                _cb(conn, msg); // 调用上层去处理报文
            }
        }
    }
    // 此函数为发送数据
    void Sender(Connection *conn)
    {
        // 刚开始是没有被设置的
        conn->_last_time_stamp = time(nullptr);
        while (true)
        {
            //logMessage(DEBUG, "sock: %d,outbuffer: %s", conn->_sock, conn->_outbuffer.c_str());
            // int n = conn->_outbuffer.size();
            ssize_t n = send(conn->_sock,conn->_outbuffer.c_str(),conn->_outbuffer.size(),0);
            if (n > 0)
            {
                //cout<<"发送成功"<<endl;
                conn->_outbuffer.erase(0, n); // 发送成功，从缓冲区清除数据
                if (conn->_outbuffer.empty())
                    break; // 为空停止发送
            }
            else
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                    break;
                else if (errno == EINTR)
                    continue;
                else
                {
                    logMessage(ERROR, "send error, %d : %s", errno, strerror(errno));
                    conn->_except_cb(conn);
                    break;
                }
            }
        }
        if (conn->_outbuffer.empty())
            EnableReadWrite(conn, true, false);
        else
            EnableReadWrite(conn, true, true);
    }
    // 此函数为处理异常
    void Excepter(Connection *conn)
    {
        conn->_last_time_stamp = time(nullptr);
        logMessage(DEBUG, "Except error display");
        if (!IsConnectionExits(conn->_sock))
            return;
        // 1. 从epoll中移除
        bool res = _epfd.DelFromEpoll(conn->_sock);
        assert(res); // 要判断
        // 2. 从我们的unorder_map中移除
        _connections.erase(conn->_sock);
        // 3. close(sock);
        close(conn->_sock);
        // 4. delete conn;
        delete conn;
    }
    // 此函数用来进行一次epoll等待的sock处理
    void LoopOnce()
    {
        int n = _epfd.WaitEpoll(_revs, _revs_num);
        for (int i = 0; i < n; i++)
        {
            int sock = _revs[i].data.fd;
            uint32_t revents = _revs[i].events;
            if (revents & EPOLLERR) // 错误--交给读取或者写入统一处理
            {
                revents |= (EPOLLIN | EPOLLOUT);
            }
            if (revents & EPOLLHUP)
            {
                revents |= (EPOLLIN | EPOLLOUT);
            }
            if (revents & EPOLLIN)
            {
                logMessage(DEBUG, "recv sock");
                if (IsConnectionExits(sock) && _connections[sock]->_recv_cb != nullptr)
                    _connections[sock]->_recv_cb(_connections[sock]);
            }
            if (revents & EPOLLOUT)
            {
                if (IsConnectionExits(sock) && _connections[sock]->_send_cb != nullptr)
                    _connections[sock]->_send_cb(_connections[sock]);
            }
        }
    }
    // 此函数为启动服务器并回调外部任务
    void Dispather(callback_t cb)
    {
        _cb = cb; // 注册方法
        int startime = time(nullptr);
        while (true)
        {

            LoopOnce();
            int nowtime = time(nullptr);
            if ((nowtime - startime) % 180 == 0)
            {
                ConnectionAliveCheck();
            }
        }
    }
    // 此函数为查询TcpServer是否添加了对该sock的管理
    bool IsConnectionExits(int sock)
    {
        return _connections.find(sock) != _connections.end();
    }
    // 此函数为检测不活跃的链接
    void ConnectionAliveCheck()
    {
        int nowtime = time(nullptr);
        for (auto iter = _connections.begin(); iter != _connections.end();)
        {
            if (iter->second->_last_time_stamp - nowtime >= 200)
            {
                auto tmp = iter->second;
                _connections.erase(iter++);
                tmp->_except_cb(tmp);
            }
            else
                iter++;
        }
    }
    // 此函数为使得TcpServer开启读取和写入功能
    void EnableReadWrite(Connection *conn, bool readable, bool writeable)
    {
        uint32_t events = ((readable ? EPOLLIN : 0) | (writeable ? EPOLLOUT : 0));
        bool res = _epfd.CtlEpoll(conn->_sock, events);
        if (!res)
        {
            logMessage(WARNING, "sock write set fail");
            exit(SET_WTITE_ERR);
        }
    }
    ~TcpServer()
    {
        if (_listensock)
            close(_listensock);
        if (_revs)
        {
            delete[] _revs;
            _revs = nullptr;
        }
        if(_rqp)
        {
            delete _rqp;
            _rqp = nullptr;
        }
        if(_rqc)
        {
            delete _rqc;
            _rqc = nullptr;
        }
        if(_rqv)
        {
            delete _rqv;
            _rqv = nullptr;
        }
        if(_rqt)
        {
            delete _rqt;
            _rqt = nullptr;
        }
    }

private:
    int _listensock;                                    // 监听套接字
    int _port;                                          // 端口号
    Epoll _epfd;                                        // epoll等待
    std::unordered_map<int, Connection *> _connections; // 管理sock和对应Con的联系
    struct epoll_event *_revs;                          // sock就绪缓冲区
    int _revs_num;                                      // 缓冲区大小
    callback_t _cb;                                     // 上层业务处理
public:
    RingQueue<int> *_rqp; // 存储point的环形队列
    RingQueue<size_t> *_rqc;   // 存储name&&pose的环形队列
    RingQueue<size_t> *_rqv;   // 存储voice的环形队列
    RingQueue<size_t> *_rqt;   // 存储触觉的环形队列
};